home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OWLSRC.PAK / COMBOBOX.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  9KB  |  386 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1997 by Borland International, All Rights Reserved
  4. //
  5. //$Revision:   10.8  $
  6. //
  7. // Implementation of TComboBox & TComboBoxData.
  8. //----------------------------------------------------------------------------
  9. #pragma hdrignore SECTION
  10. #include <owl/pch.h>
  11. #if !defined(OWL_COMBOBOX_H)
  12. # include <owl/combobox.h>
  13. #endif
  14.  
  15. OWL_DIAGINFO;
  16. DIAG_DECLARE_GROUP(OwlControl);
  17.  
  18. #if !defined(SECTION) || SECTION == 1
  19.  
  20. //
  21. // Constructor for a TComboBoxData object
  22. //
  23. TComboBoxData::TComboBoxData()
  24. :
  25.   Strings(10, 0, 10),
  26.   ItemDatas(10, 0, 10)
  27. {
  28.   SelIndex = 0;
  29. }
  30.  
  31. //
  32. // Destructor for TComboBoxData
  33. //
  34. TComboBoxData::~TComboBoxData()
  35. {
  36. }
  37.  
  38. //
  39. // Adds a given string to the "Strings" array and copies it into
  40. // "Selection" if "isSelected" is true
  41. //
  42. void
  43. TComboBoxData::AddString(const char* str, bool isSelected)
  44. {
  45.   Strings.Add(str);
  46.   if (isSelected)
  47.     Select(Strings.GetItemsInContainer()-1);
  48. }
  49.  
  50. //
  51. // Adds a given string and uint32 item to the "Strings" and "ItemDatas"
  52. // array and copies the string into "Selection" if "isSelected" is true
  53. //
  54. void
  55. TComboBoxData::AddStringItem(const char* str, uint32 itemData, bool isSelected)
  56. {
  57.   ItemDatas.Add(itemData);
  58.   AddString(str, isSelected);
  59. }
  60.  
  61. //
  62. // Selects an item at a given index.
  63. //
  64. void
  65. TComboBoxData::Select(int index)
  66. {
  67.   if (index != CB_ERR) {
  68.     SelIndex = index;
  69.     if (index < Strings.GetItemsInContainer())
  70.       Selection = Strings[index];
  71.   }
  72. }
  73.  
  74. //
  75. // Selects "str", marking the matching String entry (if any) as selected
  76. //
  77. void
  78. TComboBoxData::SelectString(const char far* str)
  79. {
  80.   int numStrings = Strings.GetItemsInContainer();
  81.   SelIndex = CB_ERR;
  82.   for (int i = 0; i < numStrings; i++)
  83.     if (strcmp(Strings[i].c_str(), str) == 0) {
  84.       SelIndex = i;
  85.       break;
  86.     }
  87.   if (Selection != str)
  88.     Selection = str;
  89. }
  90.  
  91. //
  92. // Returns the length of the selection string excluding the terminating 0
  93. //
  94. int
  95. TComboBoxData::GetSelStringLength() const
  96. {
  97.   return Selection.length();
  98. }
  99.  
  100. //
  101. // Copies the selected string into Buffer. BufferSize includes the terminating 0
  102. //
  103. void
  104. TComboBoxData::GetSelString(char far* buffer, int bufferSize) const
  105. {
  106.   if (bufferSize > 0) {
  107.     strncpy(buffer, Selection.c_str(), bufferSize-1);
  108.     buffer[bufferSize - 1] = 0;
  109.   }
  110. }
  111.  
  112. //----------------------------------------------------------------------------
  113.  
  114. //
  115. // Constructors for a TComboBox object
  116. //
  117. // By default, an MS-Windows combobox associated with the TComboBox will have
  118. // a vertical scrollbar and will maintain its entries in alphabetical order
  119. //
  120. TComboBox::TComboBox(TWindow*        parent,
  121.                      int             id,
  122.                      int x, int y, int w, int h,
  123.                      uint32           style,
  124.                      uint            textLimit,
  125.                      TModule*        module)
  126. :
  127.   TListBox(parent, id, x, y, w, h, module),
  128.   TextLimit(textLimit)
  129. {
  130.   Attr.Style = WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP |
  131.                CBS_SORT | CBS_AUTOHSCROLL | WS_VSCROLL | style;
  132.   TRACEX(OwlControl, OWL_CDLEVEL, "TComboBox constructed @" << (void*)this);
  133. }
  134.  
  135. //
  136. //
  137. //
  138. TComboBox::TComboBox(TWindow*   parent,
  139.                      int        resourceId,
  140.                      uint       textLimit,
  141.                      TModule*   module)
  142. :
  143.   TListBox(parent, resourceId, module),
  144.   TextLimit(textLimit)
  145. {
  146.   TRACEX(OwlControl, OWL_CDLEVEL, "TComboBox constructed from resource @" << (void*)this);
  147. }
  148.  
  149. //
  150. //
  151. //
  152. TComboBox::~TComboBox()
  153. {
  154.   TRACEX(OwlControl, OWL_CDLEVEL, "TComboBox destructed @" << (void*)this);
  155. }
  156.  
  157. //
  158. // Sets and selects the contents of the associated edit control to the
  159. // supplied string
  160. //
  161. void
  162. TComboBox::SetText(const char far* str)
  163. {
  164.   // If str is 0, then use empty str
  165.   //
  166.   if (!str)
  167.     str = "";
  168.  
  169.   // If not in listbox, then set the edit/static portion
  170.   //
  171.   if (SetSelString(str, -1) < 0) {
  172.     SetWindowText(str);
  173.     SetEditSel(0, strlen(str));
  174.   }
  175. }
  176.  
  177. //
  178. // Sets the text length limit member and associated control
  179. //
  180. void
  181. TComboBox::SetTextLimit(uint textlimit)
  182. {
  183.   TextLimit = textlimit;
  184.   if (GetHandle() && TextLimit != 0)
  185.     SendMessage(CB_LIMITTEXT, TextLimit-1);
  186. }
  187.  
  188. //
  189. // Returns, in the supplied reference parameters, the starting and
  190. // ending positions of the text selected in the associated edit control
  191. //
  192. // Returns CB_ERR is the combo box has no edit control
  193. //
  194. int
  195. TComboBox::GetEditSel(int& startPos, int& endPos)
  196. {
  197.   TResult  retValue = SendMessage(CB_GETEDITSEL);
  198.  
  199.   startPos = LoUint16(retValue);
  200.   endPos   = HiUint16(retValue);
  201.  
  202.   return (int)retValue;
  203. }
  204.  
  205. //
  206. // Shows or hides the drop-down list
  207. //
  208. void
  209. TComboBox::ShowList(bool show)
  210. {
  211.   if ((GetWindowLong(GWL_STYLE) & CBS_DROPDOWN) == CBS_DROPDOWN)
  212.     SendMessage(CB_SHOWDROPDOWN, show);
  213. }
  214.  
  215. static void
  216. DoAddStringToCB(string& str, void* comboBox)
  217. {
  218.   ((TListBox*)comboBox)->AddString(str.c_str());
  219. }
  220.  
  221. //
  222. // Transfers the items and selection of the combo box to or from a transfer
  223. // buffer if tdSetData or tdGetData, respectively, is passed as the
  224. // direction
  225. //
  226. // Buffer should point to a TComboBoxData which points to the data to be
  227. // transferred
  228. //
  229. // Transfer returns the size of TComboBoxData
  230. //
  231. // To retrieve the size without transferring data, pass tdSizeData as the
  232. // direction
  233. //
  234. uint
  235. TComboBox::Transfer(void* buffer, TTransferDirection direction)
  236. {
  237.   TComboBoxData* comboBoxData = (TComboBoxData*)buffer;
  238.  
  239.   if (direction == tdGetData) {
  240.     // Clear out Strings array and fill with contents of list box part
  241.     // Prescan for longest string to allow a single temp allocation
  242.     //
  243.     comboBoxData->Clear();
  244.  
  245.     int  count = GetCount();
  246.     int  maxStringLen = 0;
  247.     int  i;
  248.     for (i = 0; i < count; i++) {
  249.       int  stringLen = GetStringLen(i);
  250.       if (stringLen > maxStringLen)
  251.         maxStringLen = stringLen;
  252.     }
  253.     char*  tmpString = new char[maxStringLen+1];
  254.     for (i = 0; i < count; i++) {
  255.       GetString(tmpString, i);
  256.       comboBoxData->AddString(tmpString, false);
  257.       comboBoxData->GetItemDatas()[i] = GetItemData(i);
  258.     }
  259.     delete[] tmpString;
  260.  
  261.     // Get the sel string from the list by index, or if no index from the
  262.     // edit box
  263.     //
  264.     int selIndex = GetSelIndex();
  265.     if (selIndex >= 0) {
  266.       int  stringLen = GetStringLen(selIndex);
  267.       if (stringLen > 0) {
  268.         char* str = new char[stringLen+1];
  269.         GetString(str, selIndex);
  270.         comboBoxData->SelectString(str);
  271.         delete[] str;
  272.       }
  273.       else
  274.         comboBoxData->SelectString("");
  275.     }
  276.     else {
  277.       int  stringLen = GetWindowTextLength();
  278.       if (stringLen > 0) {
  279.         char* str = new char[stringLen+1];
  280.         GetWindowText(str, stringLen+1);
  281.         comboBoxData->SelectString(str);
  282.         delete[] str;
  283.       }
  284.       else
  285.         comboBoxData->SelectString("");
  286.     }
  287.   }
  288.   else if (direction == tdSetData) {
  289.     ClearList();
  290.     comboBoxData->GetStrings().ForEach(DoAddStringToCB, this);
  291.     for (int i = 0; i < comboBoxData->GetItemDatas().GetItemsInContainer(); i++)
  292.       SetItemData(i, comboBoxData->GetItemDatas()[i]);
  293.  
  294.     SetWindowText(comboBoxData->GetSelection().c_str());
  295.     if (comboBoxData->GetSelIndex() >= 0)
  296.       SetSelString(comboBoxData->GetSelection().c_str(), 0);
  297.   }
  298.  
  299.   return sizeof(TComboBoxData);
  300. }
  301.  
  302. //
  303. // Returns name of predefined Windows combobox class
  304. //
  305. char far*
  306. TComboBox::GetClassName()
  307. {
  308.   return "COMBOBOX";
  309. }
  310.  
  311. //
  312. // Limits the amount of text that the user can enter in the combo box's
  313. // edit control to the value of TextLimit minus 1
  314. //
  315. // Creates plain TWindow aliases for the children in the combo box so that
  316. // TWindow can handle kill focus messages for focus support.
  317. //
  318. void
  319. TComboBox::SetupWindow()
  320. {
  321.   TRACEX(OwlControl, 1, "TComboBox::SetupWindow() @ " << (void*)this);
  322.  
  323.   TListBox::SetupWindow();
  324.  
  325.   SetTextLimit(TextLimit);
  326.  
  327.   THandle hWnd = ::GetWindow(GetHandle(), GW_CHILD);
  328.   while (hWnd) {
  329.     if (!GetWindowPtr(hWnd))
  330.       (new TWindow(hWnd))->SetParent(this);
  331.     hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  332.   }
  333. }
  334.  
  335. //
  336. // Cleanup aliases created in SetupWindow
  337. //
  338. void
  339. TComboBox::CleanupWindow()
  340. {
  341.   HWND hWnd = ::GetWindow(GetHandle(), GW_CHILD);
  342.   while (hWnd) {
  343.     TWindow* wnd = GetWindowPtr(hWnd);
  344.     delete wnd;
  345.     hWnd = ::GetWindow(hWnd, GW_HWNDNEXT);
  346.   }
  347.  
  348.   // call base class
  349.   //
  350.   TListBox::CleanupWindow();
  351.  
  352.   TRACEX(OwlControl, 1, "TComboBox::CleanupWindow() @ " << (void*)this);
  353. }
  354.  
  355. #endif
  356. #if !defined(SECTION) || SECTION == 2
  357.  
  358. IMPLEMENT_STREAMABLE1(TComboBox, TListBox);
  359.  
  360. #if !defined(BI_NO_OBJ_STREAMING)
  361.  
  362. //
  363. // Reads an instance of TComboBox from the supplied ipstream
  364. //
  365. void*
  366. TComboBox::Streamer::Read(ipstream& is, uint32 /*version*/) const
  367. {
  368.   ReadBaseObject((TListBox*)GetObject(), is);
  369.   is >> GetObject()->TextLimit;
  370.   return GetObject();
  371. }
  372.  
  373. //
  374. // Writes the TComboBox to the supplied opstream
  375. //
  376. void
  377. TComboBox::Streamer::Write(opstream& os) const
  378. {
  379.   WriteBaseObject((TListBox*)GetObject(), os);
  380.   os << GetObject()->TextLimit;
  381. }
  382.  
  383. #endif  // if !defined(BI_NO_OBJ_STREAMING)
  384.  
  385. #endif
  386.